"""
API客户端，提供与外部API通信的基础设施
包含自动登录、token管理、请求重试和错误处理等功能
"""
from typing import Dict, Any, Optional
import requests
import urllib3
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from app.config.api_config import (
    API_LOGIN,
    DEFAULT_HEADERS,
    LOGIN_DATA
)
from app.utils.log_control import INFO, ERROR

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class APIClient:
    _instance = None
    _initialized = False

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self):
        if not self._initialized:
            self.session = requests.Session()
            
            # 配置重试策略
            retry_strategy = Retry(
                total=3,  # 最大重试次数
                backoff_factor=0.5,  # 重试间隔
                status_forcelist=[500, 502, 503, 504],  # 需要重试的HTTP状态码
            )
            
            # 配置适配器
            adapter = HTTPAdapter(
                max_retries=retry_strategy,
                pool_connections=10,  # 连接池大小
                pool_maxsize=10  # 最大连接数
            )
            
            # 注册适配器
            self.session.mount('http://', adapter)
            self.session.mount('https://', adapter)
            
            # 设置默认超时
            self.timeout = (5, 15)  # (连接超时, 读取超时)
            
            self.headers = DEFAULT_HEADERS.copy()
            # 添加一些必要的请求头
            self.headers.update({
                'Connection': 'keep-alive',
                'accesstoken': 'domain=.cepin.com',
                'Host': 'test-tds-standard.cepin.com',
                'X-Requested-With': 'XMLHttpRequest'
            })
            if 'accept-encoding' in self.headers:
                del self.headers['accept-encoding']

            self.token = None
            self._initialized = True
            self._login()  # 初始化时自动登录获取token

    def _login(self) -> None:
        """内部登录方法，获取token"""
        if self.token:
            INFO.logger.info("已存在有效token，跳过登录")
            return

        try:
            INFO.logger.info(f"正在请求登录接口: {API_LOGIN}")

            response = self.session.post(
                API_LOGIN,
                json=LOGIN_DATA,
                headers=self.headers,
                verify=False,
                timeout=self.timeout
            )

            result = response.json()

            if result.get('code') == 0:
                self.token = result.get('response')
                self.headers['accesstoken'] = self.token
                self.headers['Authorization'] = f'Bearer {self.token}'
                INFO.logger.info("登录成功")
            else:
                ERROR.logger.error(f"登录失败: {result.get('message')}")
                raise Exception(f"登录失败: {result.get('message')}")

        except requests.exceptions.RequestException as e:
            ERROR.logger.error(f"登录请求失败: {str(e)}")
            raise

    def request(self, method: str, url: str, data: Optional[Dict[str, Any]] = None, **kwargs) -> Dict[str, Any]:
        """发送HTTP请求"""
        try:
            if not self.token:
                self._login()

            kwargs.setdefault('headers', self.headers)
            kwargs.setdefault('verify', False)
            kwargs.setdefault('timeout', self.timeout)

            if data:
                kwargs['json'] = data
                INFO.logger.info(f"请求数据: {data}")

            response = self.session.request(method, url, **kwargs)
            result = response.json()

            if result.get('code') == 0:
                INFO.logger.info(f"{method} 请求成功: {url}")
                return result
            else:
                ERROR.logger.error(f"{method} 请求失败: {result.get('message')}")
                return result

        except requests.exceptions.RequestException as e:
            ERROR.logger.error(f"{method} 请求异常: {str(e)}")
            raise

    def get(self, url: str, **kwargs) -> Dict[str, Any]:
        """发送GET请求"""
        return self.request('GET', url, **kwargs)

    def post(self, url: str, data: Optional[Dict[str, Any]] = None, **kwargs) -> Dict[str, Any]:
        """发送POST请求"""
        return self.request('POST', url, data, **kwargs)

# 创建全局单例实例
api_client = APIClient()
